<template>
  <div>
    <el-tabs type="border-card">
      <el-tab-pane v-if="shouldHide('second')" label="秒">
        <CrontabSecond
          ref="cronsecond"
          :check="checkNumber"
          :cron="crontabValueObj"
          @update="updateCrontabValue"
        />
      </el-tab-pane>

      <el-tab-pane v-if="shouldHide('min')" label="分钟">
        <CrontabMin
          ref="cronmin"
          :check="checkNumber"
          :cron="crontabValueObj"
          @update="updateCrontabValue"
        />
      </el-tab-pane>

      <el-tab-pane v-if="shouldHide('hour')" label="小时">
        <CrontabHour
          ref="cronhour"
          :check="checkNumber"
          :cron="crontabValueObj"
          @update="updateCrontabValue"
        />
      </el-tab-pane>

      <el-tab-pane v-if="shouldHide('day')" label="日">
        <CrontabDay
          ref="cronday"
          :check="checkNumber"
          :cron="crontabValueObj"
          @update="updateCrontabValue"
        />
      </el-tab-pane>

      <el-tab-pane v-if="shouldHide('month')" label="月">
        <CrontabMonth
          ref="cronmonth"
          :check="checkNumber"
          :cron="crontabValueObj"
          @update="updateCrontabValue"
        />
      </el-tab-pane>

      <el-tab-pane v-if="shouldHide('week')" label="周">
        <CrontabWeek
          ref="cronweek"
          :check="checkNumber"
          :cron="crontabValueObj"
          @update="updateCrontabValue"
        />
      </el-tab-pane>

      <el-tab-pane v-if="shouldHide('year')" label="年">
        <CrontabYear
          ref="cronyear"
          :check="checkNumber"
          :cron="crontabValueObj"
          @update="updateCrontabValue"
        />
      </el-tab-pane>
    </el-tabs>

    <div class="popup-main">
      <div class="popup-result">
        <p class="title">时间表达式</p>
        <table>
          <thead>
            <tr>
              <th v-for="item of tabTitles" :key="item" style="width: 40px;">{{ item }}</th>
              <th>Cron 表达式</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>
                <span>{{ crontabValueObj.second }}</span>
              </td>
            </tr>
            <tr>
              <td>
                <span>{{ crontabValueObj.min }}</span>
              </td>
            </tr>
            <tr>
              <td>
                <span>{{ crontabValueObj.hour }}</span>
              </td>
            </tr>
            <tr>
              <td>
                <span>{{ crontabValueObj.day }}</span>
              </td>
            </tr>
            <tr>
              <td>
                <span>{{ crontabValueObj.month }}</span>
              </td>
            </tr>
            <tr>
              <td>
                <span>{{ crontabValueObj.week }}</span>
              </td>
            </tr>
            <tr>
              <td>
                <span>{{ crontabValueObj.year }}</span>
              </td>
            </tr>
            <tr>
              <td>
                <span>{{ crontabValueString }}</span>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <CrontabResult :ex="crontabValueString" />

      <div class="pop_btn">
        <el-button size="small" type="primary" @click="submitFill">确定</el-button>
        <el-button size="small" type="warning" @click="clearCron">重置</el-button>
        <el-button size="small" @click="hidePopup">取消</el-button>
      </div>
    </div>
  </div>
</template>
<script setup>
import { computed, onMounted, reactive, ref, watch } from 'vue'
import CrontabSecond from './second.vue'
import CrontabMin from './min.vue'
import CrontabHour from './hour.vue'
import CrontabDay from './day.vue'
import CrontabMonth from './month.vue'
import CrontabWeek from './week.vue'
import CrontabYear from './year.vue'
import CrontabResult from './result.vue'


defineOptions({
  name: 'Vcrontab'
})
const pageThis = getCurrentInstance()

const props = defineProps({
  expression: {
    type: String,
    default: ''
  },
  hideComponent: {
    type: Array,
    default: () => []
  }
})

const emit = defineEmits(['hide', 'fill'])

const tabTitles = ref(['秒', '分钟', '小时', '日', '月', '周', '年'])
const crontabValueObj = reactive({
  second: '*',
  min: '*',
  hour: '*',
  day: '*',
  month: '*',
  week: '?',
  year: ''
})

const crontabValueString = computed(() => {
  const obj = crontabValueObj
  return obj.second +
      ' ' +
      obj.min +
      ' ' +
      obj.hour +
      ' ' +
      obj.day +
      ' ' +
      obj.month +
      ' ' +
      obj.week +
      (obj.year === '' ? '' : ' ' + obj.year)
})

const shouldHide = (key) => {
  return !(props.hideComponent && props.hideComponent.includes(key))
}

const resolveExp = () => {
  if (props.expression) {
    const arr = props.expression.split(' ')
    if (arr.length >= 6) {
      const obj = {
        second: arr[0],
        min: arr[1],
        hour: arr[2],
        day: arr[3],
        month: arr[4],
        week: arr[5],
        year: arr[6] ? arr[6] : ''
      }
      Object.assign(crontabValueObj, obj)
      for (const i in obj) {
        if (obj[i]) changeRadio(i, obj[i])
      }
    }
  } else {
    clearCron()
  }
}

// 由子组件触发，更改表达式组成的字段值
const updateCrontabValue = (name, value, from) => {
  crontabValueObj[name] = value
  if (from && from !== name) {
    console.log(`来自组件 ${ from } 改变了 ${ name } ${ value }`)
    changeRadio(name, value)
  }
}

const changeRadio = (name, value) => {
  const refName = 'cron' + name
  const curRef = pageThis.refs[refName]
  if (!curRef) return

  const handleValue = {
    '*': () => 1,
    '?': () => 2,
    '-': (val) => {
      const [v1, v2] = val.split('-')
      curRef.cycle01 = isNaN(v1) ? 0 : v1
      curRef.cycle02 = v2
      return name === 'year' ? 3 : (name === 'day' || name === 'week' ? 3 : 2)
    },
    '/': (val) => {
      const [v1, v2] = val.split('/')
      curRef.average01 = isNaN(v1) ? 0 : v1
      curRef.average02 = v2
      return name === 'year' ? 4 : (name === 'day' ? 4 : 3)
    },
    'default': (val) => {
      curRef.checkboxList = val.split(',')
      return {
        'second': 4,
        'min': 4,
        'hour': 4,
        'month': 4,
        'day': 7,
        'week': 6,
        'year': 5
      }[name]
    }
  }

  const specialHandlers = {
    'day': {
      'W': (val) => {
        const [v] = val.split('W')
        curRef.workday = isNaN(v) ? 0 : v
        return 5
      },
      'L': () => 6
    },
    'week': {
      '#': (val) => {
        const [v1, v2] = val.split('#')
        curRef.average01 = isNaN(v1) ? 1 : v1
        curRef.average02 = v2
        return 4
      },
      'L': (val) => {
        const [v] = val.split('L')
        curRef.weekday = isNaN(v) ? 1 : v
        return 5
      }
    },
    'year': {
      '': () => 1
    }
  }

  let insValue
  if (value === '*') {
    insValue = handleValue['*']()
  } else if (value === '?') {
    insValue = handleValue['?']()
  } else {
    // 检查特殊处理器
    const specialHandler = specialHandlers[name]
    if (specialHandler) {
      for (const [key, handler] of Object.entries(specialHandler)) {
        if (value.includes(key)) {
          insValue = handler(value)
          break
        }
      }
    }

    // 如果没有特殊处理,使用通用处理
    if (!insValue) {
      if (value.includes('-')) {
        insValue = handleValue['-'](value)
      } else if (value.includes('/')) {
        insValue = handleValue['/'](value)
      } else {
        insValue = handleValue['default'](value)
      }
    }
  }
  curRef.radioValue = insValue
}

// 表单选项的子组件校验数字格式（通过-props传递）
const checkNumber = (value, minLimit, maxLimit) => {
  // 检查必须为整数
  value = Math.floor(value)
  if (value < minLimit) {
    value = minLimit
  } else if (value > maxLimit) {
    value = maxLimit
  }
  return value
}


const submitFill = () => {
  emit('fill', crontabValueString.value)
  emit('hide')
}

const clearCron = () => {
  // 还原选择项
  Object.assign(crontabValueObj, {
    second: '*',
    min: '*',
    hour: '*',
    day: '*',
    month: '*',
    week: '?',
    year: ''
  })
}

const hidePopup = () => {
  emit('hide')
}

watch(() => props.expression, resolveExp)

watch(() => props.hideComponent, (value) => {
  // 监听隐藏部分组件
})

onMounted(() => {
  resolveExp()
})
</script>

<style>
.pop_btn {
  text-align: center;
  margin-top: 20px;
}

.popup-main {
  position: relative;
  margin: 10px auto;
  background: #fff;
  border-radius: 5px;
  font-size: 12px;
  overflow: hidden;
}

.popup-title {
  overflow: hidden;
  line-height: 34px;
  padding-top: 6px;
  background: #f2f2f2;
}

.popup-result {
  box-sizing: border-box;
  line-height: 24px;
  margin: 25px auto;
  padding: 15px 10px 10px;
  border: 1px solid #ccc;
  position: relative;
}

.popup-result .title {
  position: absolute;
  top: -28px;
  left: 50%;
  width: 140px;
  font-size: 14px;
  margin-left: -70px;
  text-align: center;
  line-height: 30px;
  background: #fff;
}

.popup-result table {
  text-align: center;
  width: 100%;
  margin: 0 auto;
}

.popup-result table span {
  display: block;
  width: 100%;
  font-family: arial,serif;
  line-height: 30px;
  height: 30px;
  white-space: nowrap;
  overflow: hidden;
  border: 1px solid #e8e8e8;
}

.popup-result-scroll {
  font-size: 12px;
  line-height: 24px;
  height: 10em;
  overflow-y: auto;
}
</style>
